﻿using Dapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;

namespace lwzlz.Core.Repository
{
    /// <summary>
    /// 默认仓储接口实现局部类 Query
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public partial class Repository<TEntity>
    {
        public TEntity Get(object id, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.Get<TEntity>(id, transaction, commandTimeout);
        }

        public T Get<T>(object id, IDbTransaction transaction = null, int? commandTimeout = default(int?)) where T : ModelBase
        {
            return dbconn.Get<T>(id, transaction, commandTimeout);
        }

        public Task<TEntity> GetAsync(object id, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetAsync<TEntity>(id, transaction, commandTimeout);
        }

        public IEnumerable<TEntity> GetList()
        {
            return dbconn.GetList<TEntity>();
        }

        public IEnumerable<TEntity> GetList(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetList<TEntity>(whereConditions, transaction, commandTimeout);
        }

        public IEnumerable<TEntity> GetList(string whereConditions, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetList<TEntity>(whereConditions, param, transaction, commandTimeout);
        }

        public Task<IEnumerable<TEntity>> GetListAsync()
        {
            return dbconn.GetListAsync<TEntity>();
        }

        public Task<IEnumerable<TEntity>> GetListAsync(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetListAsync<TEntity>(whereConditions, transaction, commandTimeout);
        }

        public Task<IEnumerable<TEntity>> GetListAsync(string whereConditions, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetListAsync<TEntity>(whereConditions, param, transaction, commandTimeout);
        }

        public IEnumerable<TEntity> GetListPaged(int pageNumber, int rowsPerPage, string conditions, string orderby,
            object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetListPaged<TEntity>(pageNumber, rowsPerPage, conditions, orderby, param, transaction, commandTimeout);
        }

        public IEnumerable<T> GetQueryPaged<T>(int pageNumber, int rowsPerPage, string orderby, string sql, object param = null, IDbTransaction transaction = null,
            bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?)) where T : class, new()
        {
            string sqlPage = string.Format(
@"SELECT * 
    FROM (
        SELECT *, ROW_NUMBER() OVER (ORDER BY {0}) AS r_num 
            FROM ({1}) AS t1
        ) AS t2
    WHERE r_num BETWEEN ({2}-1)*{3}+1 AND {2}*{3}", orderby, sql, pageNumber, rowsPerPage);
            return dbconn.Query<T>(sqlPage, param, transaction, buffered, commandTimeout, commandType);
        }

        public IEnumerable<dynamic> GetDynamicPaged(int pageNumber, int rowsPerPage, string orderby, string sql, object param = null,
            IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            string sqlPage = string.Format(
@"SELECT * 
    FROM (
        SELECT *, ROW_NUMBER() OVER (ORDER BY {0}) AS r_num 
            FROM ({1}) AS t1
        ) AS t2
    WHERE r_num BETWEEN ({2}-1)*{3}+1 AND {2}*{3}", orderby, sql, pageNumber, rowsPerPage);
            return dbconn.Query(sqlPage, param, transaction, buffered, commandTimeout, commandType);
        }

        public Task<IEnumerable<TEntity>> GetListPagedAsync(int pageNumber, int rowsPerPage, string conditions, string orderby,
            object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.GetListPagedAsync<TEntity>(pageNumber, rowsPerPage, conditions, orderby, param, transaction, commandTimeout);
        }

        public IEnumerable<TEntity> Query(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.Query<TEntity>(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        public IEnumerable<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?)) where T : class, new()
        {
            return dbconn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        public dynamic QuerySingle(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.QuerySingle(sql, param, transaction, commandTimeout, commandType);
        }

        public IEnumerable<dynamic> QueryDynamic(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.Query(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        public Task<IEnumerable<TEntity>> QueryAsync(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.QueryAsync<TEntity>(sql, param, transaction, commandTimeout, commandType);
        }

        public Task<IEnumerable<T>> QueryAsync<T>(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?)) where T : ModelBase, new()
        {
            return dbconn.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType);
        }

        public Task<IEnumerable<dynamic>> QueryDynamicAsync(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.QueryAsync(sql, param, transaction, commandTimeout, commandType);
        }

        public TEntity QueryFirstOrDefault(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.QueryFirstOrDefault<TEntity>(sql, param, transaction, commandTimeout, commandType);
        }

        public Task<TEntity> QueryFirstOrDefaultAsync(string sql, object param = null, IDbTransaction transaction = null,
            int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
        {
            return dbconn.QueryFirstOrDefaultAsync<TEntity>(sql, param, transaction, commandTimeout, commandType);
        }

        public int RecordCount(string conditions = "", object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.RecordCount<TEntity>(conditions, param, transaction, commandTimeout);
        }

        public int RecordQueryCount(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            string countKey = "r_count";
            string sqlCount = $"SELECT COUNT(1) AS {countKey} FROM({sql}) AS t1";
            IDictionary<string, object> dic = dbconn.QuerySingle(sqlCount, param, transaction, commandTimeout);
            return Convert.ToInt32(dic[countKey]);
        }

        public Task<int> RecordCountAsync(string conditions = "", object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?))
        {
            return dbconn.RecordCountAsync<TEntity>(conditions, param, transaction, commandTimeout);
        }
    }
}
